/**
条件封装变量
**/

#ifndef CONDITION_H

#define CONDITION_H

#include <Mutex.h>
#include <pthread.h>
#include <time.h>
#include <sys/types.h>
#include <stdint.h>

typedef int64_t nses_t;		//nano seconds 纳秒

class Condition {
	public:
		enum {
			PRIVATE = 0,
			SHARED = 1
		};
		enum WakeUpType {
			WAKE_UP_ONE = 0,
			WAKE_UP_ALL = 1
		};

		Condition();
		Condition(int type);
		~Condition();

		//阻塞等待 并释放互斥量
		status_t wait(Mutex& mutex);
		status_t waitRelative(Mutex& mutex, nses_t waitTimeo);
		void signal();
		void broadcast();
		void signal(WakeUpType type){
			if(type == WAKE_UP_ONE){
				signal();
			}else{
				broadcast();
			}
		}
	
	private:
		pthread_cond_t mCond;			//条件宾亮
}

inline Condition::Condition(){
	pthread_cond_init(&mCond, NULL);
}

inline Condition::Condition(int type){
	if(type == SHARED) {
		pthread_condattr_t attr;
		pthread_condattr_init(&attr);
		pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
		pthread_cond_init(&mCond, &attr);
		pthread_condattr_destroy(&attr);
	}else {
		pthread_cond_init(&mCond, NULL);
	}
}

inline status_t Condition::wait(Mutex& mutex) {
	return -pthread_cond_wait(&mCond, &mutex.mMutex);
}

inline status_t Condition::waitRelative(Mutex& mutex, nses_t waitTime) {
	/**
	* struct timespec {
	* time_t tv_sec; // seconds 
	* long tv_nsec; // and nanoseconds 
	* };
	* struct timeval {
	* time_t tv_sec;	// seconds
	* long tv_usec;	// microseconds
	* };
	*/
	struct timeval t;
	struct timespec ts;
	gettimeofday(&t, NULL);
	ts.tv_sec = t.tv_sec;
	ts.tv_nsec = t.tv_usec * 1000;
	
	ts.tv_sec += waitTime / 1000000000;
	ts.tv_nsec += waitTime % 1000000000;
	if(ts.tv_nsec / 1000000000 > 0){
		ts_tv_sec += 1;
		ts.tv_nsec -= 1000000000;
	}
	//在指定延时内发送信号过来返回0，否则返回非0错误码
	return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
}

inline void Condition::signal(){
	pthread_cond_signal(&mCond);
}

inline void Condition::broadcast() {
	pthread_cond_broadcast(&mCond);
}

#endif
